package main

import (
	"context"
	"net"
	"strconv"
	"time"

	"gofw-im/lib/define"
	pb "gofw-im/lib/grpc"
	"gofw-im/lib/logger"
	inet "gofw-im/lib/net"

	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

func InitGrpc() (err error) {
	var (
		network, addr string
	)
	if network, addr, err = inet.ParseNetwork(conf.Base.RPCAddr); err != nil {
		logger.Error.Printf("InitGrpc ParseNetwork error : %s", err)
		return
	}
	go createServer(network, addr)
	return
}

func createServer(network string, addr string) {
	lis, err := net.Listen(network, addr)
	if err != nil {
		logger.Error.Printf("InitGrpc failed to listen : %s", err)
	}
	s := grpc.NewServer()
	pb.RegisterLogicServer(s, &server{})
	reflection.Register(s)
	logger.Info.Printf("InitGrpc to listen addr: %s", addr)
	err = s.Serve(lis)
	if err != nil {
		logger.Error.Printf("InitGrpc failed to listen : %s", err)
	}
}

type server struct{}

func (rpc *server) Connect(ctx context.Context, request *pb.ConnArg) (response *pb.ConnReply, err error) {
	if request == nil {
		err = ErrConnectArgs
		logger.Error.Printf("Connect() error(%v)", err)
		return
	}
	logger.Info.Printf("connect request: %v", request)

	response = &pb.ConnReply{}

	key := getKey(request.Auth)
	logger.Info.Printf("logic rpc key:%s", key)
	userInfo, err := RedisCli.HGetAll(key).Result()
	if err != nil {
		logger.Info.Printf("RedisCli HGetAll key :%s , err:%s", key, err)
	}
	response.Uid = userInfo["UserId"]
	roomUserKey := getRoomUserKey(strconv.Itoa(int(request.RoomId)))
	if response.Uid == "" {
		response.Uid = define.NO_AUTH
	} else {
		userKey := getKey(response.Uid)
		logger.Info.Printf("logic redis set uid serverId:%s, serverId : %s", userKey, request.ServerId)
		validTime := define.REDIS_BASE_VALID_TIME * time.Second
		err = RedisCli.Set(userKey, request.ServerId, validTime).Err()
		if err != nil {
			logger.Info.Printf("logic set err:%s", err)
		}
		RedisCli.HSet(roomUserKey, response.Uid, userInfo["UserName"])
	}
	logger.Info.Printf("logic rpc uid:%s", response.Uid)
	count := RedisCli.Incr(getKey(strconv.FormatInt(int64(request.RoomId), 10))).Val()
	roomUserInfo, err := RedisCli.HGetAll(roomUserKey).Result()
	if err != nil {
		logger.Info.Printf("RedisCli HGetAll roomUserInfo key:%s, err: %s", roomUserKey, err)
	}
	if err = RedisPublishRoomInfo(request.RoomId, int(count), roomUserInfo); err != nil {
		logger.Error.Printf("Count redis RedisPublishRoomCount err: %s", err)
		return
	}
	return
}

func (rpc *server) Disconnect(ctx context.Context, request *pb.DisconnArg) (response *pb.DisconnReply, err error) {
	// 房间人数减少
	count := RedisCli.Decr(getKey(strconv.FormatInt(int64(request.RoomId), 10))).Val()
	err = RedisCli.HDel(getRoomUserKey(strconv.Itoa(int(request.RoomId))), request.Uid).Err()
	if err != nil {
		logger.Error.Printf("HDel getRoomUserKey err : %s", err)
	}
	if err = RedisPublishRoomCount(int32(request.RoomId), int(count)); err != nil {
		logger.Error.Printf("Count redis RedisPublishRoomCount err: %s", err)
		return
	}
	return
}
